package arena.soldier;

import gameframework.base.MoveStrategyKeyboard;
import gameframework.base.MoveStrategyRandom;
import gameframework.game.GameMovableDriverDefaultImpl;
import gameframework.game.GameUniverse;
import gameframework.game.MoveBlockerChecker;
import gameframework.game.MoveBlockerCheckerDefaultImpl;
import gameframework.game.SpriteManagerDefaultImpl;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Timer;

import arena.base.ArenaMoveBlockers;
import arena.base.HeroMoveStrategy;
import arena.base.MonsterMovableDriver;

public class HeroMan extends SoldierAbstract {
	private static final int FORCE = 15;
	public static final int HEALTHPOINTS = 20;
	public static final int MAGIC = 100;
	public static final int RENDERING_SIZE = 60;
	
	public boolean isFighting =false;	
	protected boolean movable = true;
	private final SpriteManagerDefaultImpl spriteManager;
	protected boolean vulnerable = false;
	protected int vulnerableTimer = 0;
	
	private HeroMoveStrategy moveStrat;
	private GameUniverse universe;
	private Canvas canvas;
	private Timer timer;
	
	private static HeroMan uniqueInstance;

	private HeroMan(String nom, Canvas defaultCanvas,GameUniverse universe) {		
		super(nom, HEALTHPOINTS, FORCE);
		timer = createTimer();
		spriteManager = new SpriteManagerDefaultImpl("images/Hero3.gif",
				defaultCanvas, RENDERING_SIZE, 5);
		spriteManager.setTypes(
				"up",
				"left", "down", "right",				
				"attackLeft","attackDown","attackRight","attackUp", "static", "unused");
		this.magic =100;
		this.universe = universe;
		this.canvas = defaultCanvas;
	}
	
	public static synchronized HeroMan getInstance(String nom, Canvas defaultCanvas,GameUniverse universe2) {
		if (uniqueInstance == null)
			uniqueInstance = new HeroMan(nom, defaultCanvas,universe2);
		return uniqueInstance;
    }
	
	public SpriteManagerDefaultImpl getSpriteManager(){
		return spriteManager;
	}

	public void heal() { //XXX resurrection allowed
		healthPoints = HEALTHPOINTS;
	}
	
	public void setInvulnerable(int timer) {
		vulnerableTimer = timer;
	}

	public boolean isVulnerable() {
		return (vulnerableTimer <= 0);
	}
		
	public void setFighting(boolean isFighting) {
		if(this.isFighting==false){
		this.isFighting = isFighting;
		if (isFighting)
			timer.start();
		}
	}

	public boolean isFighting() {
		return isFighting;
	}

	private Timer createTimer() {
		ActionListener action = new ActionListener() {
			public void actionPerformed(ActionEvent event) {
				isFighting = false;
				timer.stop();
			}
		};
		return new Timer(300, action);
	}
		
	public void setMoveStrategy(MoveStrategyKeyboard keyStr) {
		moveStrat = (HeroMoveStrategy) keyStr;
	}

	public HeroMoveStrategy getMoveStrategy() {
		return moveStrat;
	}

	public void oneStepMoveAddedBehavior() {
		if (movable) {
			spriteManager.increment();
			if (!isVulnerable()) {
				vulnerableTimer--;
			}
		}
	}

	public Rectangle getBoundingBox() {
		return (new Rectangle(0, 0, RENDERING_SIZE, RENDERING_SIZE));
	}
	
	@Override
	public void draw(Graphics g) {
		drawMagicBar(g);
		drawBarLife(g);
		String spriteType = "";
		Point tmp = getSpeedVector().getDirection();
		movable = true;
		if(this.timer.isRunning()&&tmp.getY() == -1){
			spriteType = "attackUp";
		}
		else if(this.timer.isRunning()&&tmp.getX() == 1){
			spriteType = "attackRight";
		}
		else if(this.timer.isRunning()&&tmp.getX() == -1){
			spriteType = "attackLeft";
		}
		else if(this.timer.isRunning()&&tmp.getY() == 1){
			spriteType = "attackDown";
		}
		else if (tmp.getX() == 1) {
			spriteType += "right";
		}

		else if (tmp.getX() == -1) {
			spriteType += "left";
		} else if (tmp.getY() == 1) {
			spriteType += "down";
		} else if (tmp.getY() == -1) {
			spriteType += "up";
		}
			
		else {
			spriteType = "static";
			spriteManager.reset();
			movable = false;
		}
				
		spriteManager.setType(spriteType);
		spriteManager.draw(g, getPosition());
	}

	@Override
	public float getHealthPointAtBeginning() {
		return HEALTHPOINTS;
	}
	@Override
	public float getMagicAtBeginning() {
		return MAGIC;
	}
	@Override
	public float getMagic() {
		return this.magic;
	}

	public void drawBarLife (Graphics g){
		int lifeBarWidth = getBoundingBox().width/2;
		float life = (getHealthPoints()/getHealthPointAtBeginning());
		g.setColor(Color.BLACK);
		g.drawRect(this.getPosition().x+(getBoundingBox().width)/4, this.getPosition().y, lifeBarWidth, 7);
		
		if (life > 0.33){
			g.setColor(Color.GREEN);
		}
		else
			g.setColor(Color.RED);

		//Drawing life bar inside
		g.fillRect((this.getPosition().x+(getBoundingBox().width)/4)+1,this.getPosition().y+1, (int) ((lifeBarWidth-1)*life), 6);
	}
	public void drawMagicBar (Graphics g){
		int magicBarWidth = getBoundingBox().width/2;
		float magic = (getMagic()/getMagicAtBeginning());
		g.setColor(Color.BLACK);
		g.drawRect(this.getPosition().x+(getBoundingBox().width)/4, this.getPosition().y-10, magicBarWidth, 7);		
		g.setColor(Color.cyan);
		
		//Drawing magic bar inside
		g.fillRect((this.getPosition().x+(getBoundingBox().width)/4)+1,this.getPosition().y+1-10, (int) ((magicBarWidth-1)*magic), 6);
	}

	@Override
	public boolean isEnrage() {
		return false;
	}

	@Override
	public void setEnrage(int timer) {
	}
		
	public void createTower(){	
		if(magic >= 50){
			this.magic = magic - 50;		
			
			System.out.println("Construction de la tourelle");
			MoveBlockerChecker moveBlockerChecker = new MoveBlockerCheckerDefaultImpl();
			moveBlockerChecker.setMoveBlockerRules(new ArenaMoveBlockers());
			GameMovableDriverDefaultImpl monsterDriv = new MonsterMovableDriver();
			MoveStrategyRandom ranStr = new MoveStrategyRandom();
			monsterDriv.setStrategy(ranStr);
			monsterDriv.setmoveBlockerChecker(moveBlockerChecker);
			Tower t = new Tower("tower", canvas,universe);
			t.setPosition(this.getPosition());
			universe.addGameEntity(t);
			t.setDriver(monsterDriv);
		}
	}
	
	public void setUniverse(GameUniverse universe){
		this.universe = universe;
	}
}		